package com.espirit.file;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

public final class CompressFileUtil {

	private CompressFileUtil() {

	}

	public static void compress(String resoucesPath, String targetPath, String targetName) throws Exception {
		FileSystem fileSystem = FileSystems.getDefault();
		Path srcPath = fileSystem.getPath(resoucesPath);
		Path tgtPath = fileSystem.getPath(targetPath);
		compress(srcPath, tgtPath, targetName);
	}

	public static void compress(final Path resoucesPath, Path targetPath, String targetName) throws Exception {
		if (!Files.exists(targetPath)) {
			Files.createDirectories(targetPath);
		}
		FileSystem fileSystem = FileSystems.getDefault();
		Path zipPath = fileSystem.getPath(targetPath.toString(), targetName);
		URI uri = URI.create("jar:" + zipPath.toUri());
		Map<String, String> env = new HashMap<>(1);
		env.put("create", "true");
		env.put("encoding", "UTF-8");
		final FileSystem zipfs = FileSystems.newFileSystem(uri, env);
		Files.walkFileTree(resoucesPath, new SimpleFileVisitor<Path>() {
			@Override
			public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
				Path targetPath = resoucesPath.relativize(file);
				Files.copy(file, zipfs.getPath(targetPath.toString()), StandardCopyOption.REPLACE_EXISTING);
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
				Path targetPath = resoucesPath.relativize(dir);
				if (StringUtils.isNotBlank(targetPath.toString())) {
					Files.createDirectories(zipfs.getPath(targetPath.toString()));
				}
				return FileVisitResult.CONTINUE;
			}
		});

		IOUtils.closeQuietly(zipfs);
	}

	public static void uncompress(final Path zip, final Path targetRoot) throws IOException, URISyntaxException {
		final FileSystem fs = FileSystems.getDefault();
		if (!Files.exists(targetRoot)) {
			Files.createDirectories(targetRoot);
		}
		URI zipUri = zip.toUri();
		URI uri = new URI("jar:" + zipUri.getScheme(), zipUri.getPath(), null);
		Map<String, String> env = new HashMap<>(1);
		env.put("create", String.valueOf(!Files.exists(zip)));
		env.put("encoding", "UTF-8");
		try (FileSystem zipfs = FileSystems.newFileSystem(uri, env);) {
			Files.walkFileTree(zipfs.getPath("/"), new SimpleFileVisitor<Path>() {
				@Override
				public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
					Path targetFilePath = fs.getPath(targetRoot.toString(), file.toString());
					if (!Files.exists(targetFilePath.getParent())) {
						Files.createDirectories(targetFilePath.getParent());
					}
					Files.copy(file, targetFilePath, StandardCopyOption.REPLACE_EXISTING);
					return FileVisitResult.CONTINUE;
				}
			});
		}
	}
}
